﻿namespace GoodAdmin.Core;

public static class SqlSugarSetup
{
    
    public static void AddSqlSugar(this IServiceCollection services)
    {
        // 初始化数据库表结构及种子数据
        DbContext.DbConfigs.ConnectionConfigs.ForEach(config =>
        {
            
            //是否初始化数据表
            if (config.EnableInitDb)
            {
                InitDb(config);
            }
            //是否更新种子数据
            if (config.EnableSeedData)
            {
                InitDbData( config);
            }
        });
        
        services.AddSingleton<ISqlSugarClient>(DbContext.Db);
    }

    

    /// <summary>
    /// 初始化数据库
    /// </summary>
    /// <param name="config"></param>
    private static void InitDb(DbConnectionConfig config)
    {
        SqlSugarScopeProvider dbProvider = DbContext.Db.GetConnectionScope(config.ConfigId);
        dbProvider.DbMaintenance.CreateDatabase();//创建数据库
        // 获取所有实体表-初始化表结构
        var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false));
        if (!entityTypes.Any()) return;//没有就退出
        foreach (var entityType in entityTypes)
        {
            var tenantAtt = entityType.GetCustomAttribute<TenantAttribute>();//获取Sqlsugar多租户特性
            if (tenantAtt == null && config.ConfigId.ToString() != SqlSugarConst.MainConfigId) continue;//如果没有设置数据库ID，那么就默认为主数据
            if (tenantAtt != null && tenantAtt.configId.ToString() != config.ConfigId.ToString()) continue;//如果特性存在并且租户ID是当前数据库ID
            var splitTable = entityType.GetCustomAttribute<SplitTableAttribute>();//获取自动分表特性
            if (splitTable == null)//如果特性是空
                dbProvider.CodeFirst.InitTables(entityType);//普通创建
            else
                dbProvider.CodeFirst.SplitTables().InitTables(entityType);//自动分表创建
        }
    }

    /// <summary>
    /// 初始化数据库数据
    /// </summary>
    private static void InitDbData(DbConnectionConfig config)
    {
        SqlSugarScopeProvider dbProvider = DbContext.Db.GetConnectionScope(config.ConfigId);
        // 获取所有种子配置-初始化数据
        var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
            && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))));
        if (!seedDataTypes.Any()) return;
        
        foreach (var seedType in seedDataTypes)
        {
            var instance = Activator.CreateInstance(seedType);

            var hasDataMethod = seedType.GetMethod("HasData");
            var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
            if (seedData == null) continue;

            var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();//获取实体类型
            var tenantAtt = entityType.GetCustomAttribute<TenantAttribute>();//获取sqlsugar租户特性
            if (tenantAtt != null && tenantAtt.configId.ToString() != config.ConfigId.ToString()) continue;//如果不是当前租户的就下一个

            var entityInfo = dbProvider.EntityMaintenance.GetEntityInfo(entityType);
            if (entityInfo.Columns.Any(u => u.IsPrimarykey))
            {
                // 按主键进行批量增加和更新
                var storage = dbProvider.CopyNew().StorageableByObject(seedData.ToList()).ToStorage();
                storage.AsInsertable.ExecuteCommand();
                //是否需要更新数据库已有种子数据
                var ignoreUpdate = hasDataMethod.GetCustomAttribute<IgnoreUpdateAttribute>();
                //如果没有IgnoreUpdateAttribute，那么就更新。（默认没有）
                if (ignoreUpdate == null) storage.AsUpdateable.ExecuteCommand();
            }
            else
            {
                // 无主键则只进行插入
                if (!dbProvider.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any())
                    dbProvider.InsertableByObject(seedData.ToList()).ExecuteCommand();
            }
        }
    }
}